package com.qzsoft.zhjd.materiel.modules.materielapi.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.qzsoft.jeemis.common.utils.ConvertDictUtils;
import com.qzsoft.jeemis.repository.sys.dao.BasicCodeitemDao;
import com.qzsoft.jeemis.repository.sys.entity.BasicCodeitemEntity;
import com.qzsoft.system.modules.zhjdsysdept.entity.ZhjdSysDeptEntity;
import com.qzsoft.system.modules.zhjdsysdept.service.ZhjdSysDeptService;
import com.qzsoft.zhjd.common.enums.BizCode;
import com.qzsoft.zhjd.common.enums.YesOrNo;
import com.qzsoft.zhjd.common.utils.RenExceptionUtils;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.MaterielItemBindDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.MaterielItemUnbindDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.MaterielItemUpdateDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.MaterielItemViewDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.PlatformDataSendDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.SupplierAndProjectSaveDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.SupplierAndProjectViewDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.SysUserViewDto;
import com.qzsoft.zhjd.materiel.modules.materielapi.dto.WeightDataType;
import com.qzsoft.zhjd.materiel.modules.materielapi.service.MaterielApiService;
import com.qzsoft.zhjd.materiel.modules.materieldata.enmus.MaterielDataSourceEnum;
import com.qzsoft.zhjd.materiel.modules.materieldata.entity.MaterielDataEntity;
import com.qzsoft.zhjd.materiel.modules.materieldata.service.MaterielDataService;
import com.qzsoft.zhjd.materiel.modules.materieldevice.entity.MaterielDeviceEntity;
import com.qzsoft.zhjd.materiel.modules.materieldevice.service.MaterielDeviceService;
import com.qzsoft.zhjd.materiel.modules.materielitem.dto.MaterielItemBaseSaveDto;
import com.qzsoft.zhjd.materiel.modules.materielitem.dto.MaterielItemBaseSelectDto;
import com.qzsoft.zhjd.materiel.modules.materielitem.entity.MaterielItemBaseEntity;
import com.qzsoft.zhjd.materiel.modules.materielitem.service.MaterielItemBaseService;
import com.qzsoft.zhjd.materiel.modules.materieloperator.entity.MaterielOperatorEntity;
import com.qzsoft.zhjd.materiel.modules.materieloperator.service.MaterielOperatorService;
import com.qzsoft.zhjd.materiel.modules.materielproject.entity.MaterielProjectEntity;
import com.qzsoft.zhjd.materiel.modules.materielproject.service.MaterielProjectService;
import com.qzsoft.zhjd.materiel.modules.materielsupplier.entity.MaterielSupplierEntity;
import com.qzsoft.zhjd.materiel.modules.materielsupplier.service.MaterielSupplierService;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName MaterielApiServiceImpl
 * @Description 物料API业务接口实现
 * @author linhuawei
 * @since 2022-04-05
 */
@Slf4j
@Service
public class MaterielApiServiceImpl implements MaterielApiService {

    @Value("${zhjd.upload.path}")
    private String uploadPath;

    @Value("${zhjd.upload.localhostAddr}")
    private String localhostAddr;

    @Autowired
    private MaterielItemBaseService materielItemBaseService;

    @Autowired
    private MaterielSupplierService materielSupplierService;

    @Autowired
    private MaterielProjectService materielProjectService;

    @Autowired
    private ZhjdSysDeptService zhjdSysDeptService;

    @Autowired
    private MaterielOperatorService materielOperatorService;

    @Autowired
    private BasicCodeitemDao itemMapper;

    @Autowired
    private MaterielDataService materielDataService;

    @Autowired
    private MaterielDeviceService materielDeviceService;

    @Override
    public List<SupplierAndProjectViewDto> getCooperates(String baseCode) {
        QueryWrapper<MaterielSupplierEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enable", YesOrNo.yes.getValue());
        queryWrapper.eq("base_code", baseCode);
        queryWrapper.select("id,name");
        List<MaterielSupplierEntity> list = materielSupplierService.list(queryWrapper);
        List<SupplierAndProjectViewDto> result = new ArrayList<SupplierAndProjectViewDto>();
        if (null != list) {
            SupplierAndProjectViewDto dto;
            for (MaterielSupplierEntity entity : list) {
                dto = new SupplierAndProjectViewDto();
                dto.setId(entity.getId());
                dto.setName(entity.getName());
                result.add(dto);
            }
        }
        return result;
    }

    @Override
    public void saveCooperates(SupplierAndProjectSaveDto dto) {
        MaterielSupplierEntity entity = new MaterielSupplierEntity();
        entity.setId(dto.getId());
        entity.setName(dto.getName());
        entity.setBaseCode(dto.getBasecode());
        entity.setEnable(YesOrNo.yes.getValue());
        materielSupplierService.save(entity);
    }

    @Override
    public List<SupplierAndProjectViewDto> getProjectList(String baseCode) {
        QueryWrapper<MaterielProjectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enable", YesOrNo.yes.getValue());
        queryWrapper.eq("base_code", baseCode);
        queryWrapper.select("id,name");
        List<MaterielProjectEntity> list = materielProjectService.list(queryWrapper);
        List<SupplierAndProjectViewDto> result = new ArrayList<SupplierAndProjectViewDto>();
        if (null != list) {
            SupplierAndProjectViewDto dto;
            for (MaterielProjectEntity entity : list) {
                dto = new SupplierAndProjectViewDto();
                dto.setId(entity.getId());
                dto.setName(entity.getName());
                result.add(dto);
            }
        }
        return result;
    }

    @Override
    public void saveProject(SupplierAndProjectSaveDto dto) {
        MaterielProjectEntity entity = new MaterielProjectEntity();
        entity.setId(dto.getId());
        entity.setName(dto.getName());
        entity.setBaseCode(dto.getBasecode());
        entity.setEnable(YesOrNo.yes.getValue());
        materielProjectService.save(entity);
    }

    @Override
    public List<SysUserViewDto> getOperators(String baseCode) {
        // 获取基地信息
        ZhjdSysDeptEntity dept = zhjdSysDeptService.getBaseByCode(baseCode);
        if (null == dept) {
            return new ArrayList<SysUserViewDto>();
        }

        // 获取用户列表
        QueryWrapper<MaterielOperatorEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_code", baseCode);
        queryWrapper.eq("enable", YesOrNo.yes.getValue());
        queryWrapper.orderByAsc("name");
        List<MaterielOperatorEntity> list = materielOperatorService.list(queryWrapper);
        List<SysUserViewDto> result = new ArrayList<SysUserViewDto>();
        if (ObjectUtils.isNotEmpty(list)) {
            SysUserViewDto dto;
            for (MaterielOperatorEntity entity : list) {
                dto = new SysUserViewDto();
                dto.setId(entity.getId());
                dto.setDisplay(entity.getName());
                dto.setPwd(entity.getPassword().toUpperCase());
                dto.setName(entity.getAccount());
                result.add(dto);
            }
        }

        // 添加基地信息
        // TODO 地磅设备端需要获取场站信息，根据协商，将场站信息放在用户列表中，设置pwd=0做标记
        SysUserViewDto dto = new SysUserViewDto();
        dto.setId(dept.getId());
        dto.setPwd("0");
        dto.setName(dept.getCode());
        dto.setDisplay(dept.getName());
        result.add(dto);
        return result;
    }

    @Override
    public List<MaterielItemViewDto> getItemList(String baseCode) {
        List<MaterielItemBaseSelectDto> list = materielItemBaseService.getBind(baseCode);
        List<MaterielItemViewDto> result = new ArrayList<MaterielItemViewDto>();
        if (null != list) {
            MaterielItemViewDto dto;
            for (MaterielItemBaseSelectDto select : list) {
                dto = new MaterielItemViewDto();
                dto.setId(select.getMaterielItemId());
                dto.setCategory(select.getMaterielCategoryName());
                dto.setName(select.getMaterielItemName());
                dto.setSpec(select.getMaterielItemSpec());
                dto.setUnit(select.getMaterielItemUnitLabel());
                if (null == select.getConvRate()) {
                    dto.setConvRate(new BigDecimal(1));
                } else {
                    dto.setConvRate(select.getConvRate());
                }
                dto.setUpperLimit(select.getUpperLimit());
                dto.setLowerLimit(select.getLowerLimit());
                if ("成品料".equals(select.getMaterielCategoryName()) || "成品材料".equals(select.getMaterielCategoryName())) {
                    dto.setKind(1);
                } else {
                    dto.setKind(0);
                }
                result.add(ConvertDictUtils.formatDicData(dto));
            }
        }
        return result;
    }

    @Override
    public List<MaterielItemUnbindDto> getUnbindItemList(String baseCode) {
        List<MaterielItemBaseSelectDto> list = materielItemBaseService.getUnbind(baseCode);
        List<MaterielItemUnbindDto> result = new ArrayList<MaterielItemUnbindDto>();
        if (null != list) {
            MaterielItemUnbindDto dto;
            for (MaterielItemBaseSelectDto select : list) {
                dto = new MaterielItemUnbindDto();
                dto.setId(select.getMaterielItemId());
                dto.setCategory(select.getMaterielCategoryName());
                dto.setName(select.getMaterielItemName());
                dto.setSpec(select.getMaterielItemSpec());
                if (null == select.getConvRate()) {
                    dto.setConvRate(new BigDecimal(1));
                } else {
                    dto.setConvRate(select.getConvRate());
                }
                if ("成品料".equals(select.getMaterielCategoryName()) || "成品材料".equals(select.getMaterielCategoryName())) {
                    dto.setKind(1);
                } else {
                    dto.setKind(0);
                }
                result.add(dto);
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> bindItem(MaterielItemBindDto dto) {
        // 解除绑定材料
        List<String> itemIds = dto.getUnbind();
        if (ObjectUtils.isNotEmpty(itemIds)) {
            QueryWrapper<MaterielItemBaseEntity> queryWrapper = new QueryWrapper<MaterielItemBaseEntity>();
            queryWrapper.eq("base_code", dto.getBasecode());
            queryWrapper.in("materiel_item_id", itemIds);
            materielItemBaseService.remove(queryWrapper);
        }

        // 绑定材料列表
        MaterielItemBaseSaveDto saveDto = new MaterielItemBaseSaveDto();
        saveDto.setBaseCode(dto.getBasecode());
        saveDto.setItemIdList(dto.getBind());
        return materielItemBaseService.saveReturnErrors(saveDto);
    }

    @Override
    public void updateItem(List<MaterielItemUpdateDto> list) {
        UpdateWrapper<MaterielItemBaseEntity> updateWrapper = new UpdateWrapper<>();
        for (MaterielItemUpdateDto dto : list) {
            // 基地编号、材料主键不可为空
            if (ObjectUtils.isEmpty(dto.getBasecode()) || ObjectUtils.isEmpty(dto.getId())) {
                continue;
            }

            // 执行更新操作
            updateWrapper.clear();
            updateWrapper.eq("base_code", dto.getBasecode());
            updateWrapper.eq("materiel_item_id", dto.getId());
            updateWrapper.set("upper_limit", dto.getPositiveDifference());
            updateWrapper.set("lower_limit", dto.getNegativeDifference());
            updateWrapper.set("conv_rate", dto.getUnitConversion());
            materielItemBaseService.update(updateWrapper);
        }

    }

    @Override
    public List<WeightDataType> getWeightType() {
        // 获取字典数据
        QueryWrapper<BasicCodeitemEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("codeid", "WEIGHT_TYPE");
        List<BasicCodeitemEntity> list = itemMapper.selectList(queryWrapper);

        // 获取子类
        List<WeightDataType> result = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(list)) {
            WeightDataType type;
            for (BasicCodeitemEntity item : list) {
                if ("WEIGHT_TYPE".equals(item.getPptr())) {
                    continue;
                }

                type = new WeightDataType();
                type.setId(item.getCode());
                type.setName(item.getDescription());
                type.setPid(item.getPptr());
                result.add(type);
            }
        }

        // 返回结果
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveMaterielData(PlatformDataSendDto dto, MultipartFile[] file) {
        // 这里临时处理综合管控、养护基地同时传的问题
        String deviceCode = dto.getSiteNO();
        if ("QTXM1#CZ1#TS".equals(deviceCode)) {
            dto.setSiteNO("JD02TS1");

            String weightCode = dto.getWstID().replace("QTXM1#CZ1#TS", "JD02TS1");
            dto.setWstID(weightCode);
        }

        // 判断地磅设备是否存在
        MaterielDeviceEntity device = materielDeviceService.getByCode(dto.getSiteNO());
        if (null == device) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "地磅设备[" + dto.getSiteNO() + "]不存在");
        }

//        // 判断材料是否存在
//        QueryWrapper<MaterielItemEntity> queryWrapper = new QueryWrapper<MaterielItemEntity>();
//        queryWrapper.eq("id", dto.getMaterialID());
//        Integer count = materielItemService.count(queryWrapper);
//        if (null == count || 0 == count) {
//            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "过磅材料[" + dto.getMaterialID() + "]不存在");
//        }

        // 如果当前磅房、当前磅单已经存在，删除历史数据
        QueryWrapper<MaterielDataEntity> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.eq("device_code", device.getCode());
        deleteWrapper.eq("weight_code", dto.getWstID());
        materielDataService.remove(deleteWrapper);

        // TODO 其他校验后续添加

        // 添加参数
        MaterielDataEntity dataEntity = new MaterielDataEntity();
        dataEntity.setBaseCode(device.getBaseCode());// 基地编号
        dataEntity.setDeviceCode(device.getCode());// 地磅编号
        dataEntity.setMaterielItemId(dto.getMaterialID());// 物料唯一标识
        dataEntity.setOperatorId(dto.getOperatorID());// 操作员
        dataEntity.setSupplierId(dto.getProviderID());// 供应商主键
        dataEntity.setProjectId(dto.getAcceptorID());// 用料项目/单位主键
        dataEntity.setWeightCode(dto.getWstID());// 磅单编号
        dataEntity.setWeightType(dto.getWstTypeID());// 过磅类型：0=收料，1=发料
        dataEntity.setWeightDataType(dto.getRSTypeID());// 数据类型（采购、销售等）
        dataEntity.setWeightDataSource(MaterielDataSourceEnum.WEIGH.getValue());// 数据来源
        dataEntity.setDeviationType(dto.getOffsetResult());// 偏差：0=正常，1=超负差，2=超正差
        dataEntity.setDeviationRatio(dto.getRealOffset());// 偏差率
        dataEntity.setUpperLimit(dto.getUpperLimit());// 正差值
        dataEntity.setLowerLimit(dto.getLowerLimit());// 负差值
        dataEntity.setGrossWeight(dto.getGrossWeight());// 毛重/t
        dataEntity.setTareWeight(dto.getTareWeight());// 皮重/t
        dataEntity.setDeductionRatio(dto.getDeductRate());// 扣重占比
        dataEntity.setDeductionWeight(dto.getDeductWeight());// 扣重/t
        dataEntity.setNetWeight(dto.getSuttleWeight());// 净重/t
        dataEntity.setWeight(dto.getRealWeight());// 实际重量
        dataEntity.setQuantity(dto.getRealNum());// 实际数量
        dataEntity.setWaybillCode(dto.getRawBillNO());// 运单编号
        dataEntity.setWaybillQuantity(dto.getRawBillWeight());// 运单重量/t
        dataEntity.setWaybillQuantity(dto.getRawBillNum());// 运单数量
        dataEntity.setExitTime(dto.getOutTime());// 出场时间
        dataEntity.setEntryTime(dto.getInTime());// 进场时间
        dataEntity.setCarNumber(dto.getVLP());// 车牌号
        dataEntity.setDisable(dto.getDisposed());// 是否废弃：0=否，1=是
        dataEntity.setDisableReason(dto.getReason());// 废弃原因
        dataEntity.setRemark(dto.getRemark());// 备注信息
        dataEntity.setChanged(YesOrNo.no.getValue());// 是否变化
        dataEntity.setPrintTimes(dto.getPrintCnt());// 打印次数

        // create_date 入库时间
        // deleted 是否删除 0已删除 1未删除
        // prince 价格
        // total_prince 总价
        // reason 废弃原因
        // deviation_type_status 超出差值状态
        // project_id 项目id
        // contract_id 合同id
        // old_weight_code 原始磅单编号

        // 保存图片信息
        // waybill_image
        // entry_image_one 进磅图片1
        // entry_image_two 进磅图片2
        // entry_image_three 进磅图片3
        // entry_image_four 进磅图片4
        // exit_image_one 出磅图片1
        // exit_image_two 出磅图片2
        // exit_image_three 出磅图片3
        // exit_image_four 出磅图片4
        if (null != file && 0 < file.length) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            String path = "/upload/weight/" + sdf.format(new Date()) + "/";
            File targetFile = new File(uploadPath + path);
            if (!targetFile.exists() || !targetFile.isDirectory()) {
                targetFile.mkdirs();
            }
            String filepath;
            // 最多传9张图片：4进场+4出场+1运单
            for (int i = 0, len = file.length; i < len && i < 9; i++) {
                try {
                    filepath = path + file[i].getOriginalFilename().replace("QTXM1#CZ1#TS", "JD02TS1");
                    targetFile = new File(uploadPath + filepath);
                    file[i].transferTo(targetFile);

                    if (filepath.endsWith("_1.jpg")) {// 进磅车头
                        dataEntity.setEntryImageOne(localhostAddr + filepath);
                    } else if (filepath.endsWith("_2.jpg")) {// 进磅车位
                        dataEntity.setEntryImageTwo(localhostAddr + filepath);
                    } else if (filepath.endsWith("_3.jpg")) {// 进磅车身
                        dataEntity.setEntryImageThree(localhostAddr + filepath);
                    } else if (filepath.endsWith("_4.jpg")) {// 进磅磅房
                        dataEntity.setEntryImageFour(localhostAddr + filepath);
                    } else if (filepath.endsWith("_5.jpg")) {// 出磅车头
                        dataEntity.setExitImageOne(localhostAddr + filepath);
                    } else if (filepath.endsWith("_6.jpg")) {// 出磅车位
                        dataEntity.setExitImageTwo(localhostAddr + filepath);
                    } else if (filepath.endsWith("_7.jpg")) {// 出磅车身
                        dataEntity.setExitImageThree(localhostAddr + filepath);
                    } else if (filepath.endsWith("_8.jpg")) {// 出磅磅房
                        dataEntity.setExitImageFour(localhostAddr + filepath);
                    } else if (filepath.endsWith("_9.jpg")) {// 运单图片
                        dataEntity.setWaybillImage(localhostAddr + filepath);
                    }
                } catch (IOException e) {
                    log.error("磅单图片上传失败：size=" + i);
                }
            }
        }

        // 数据添加
        materielDataService.save(dataEntity);
    }
    
    @Override
    public List<MaterielDataEntity> getMaterielData(String weightCode) {
        QueryWrapper<MaterielDataEntity> queryWrapper = new QueryWrapper<MaterielDataEntity>();
        queryWrapper.eq("device_code", weightCode);
        queryWrapper.eq("changed", YesOrNo.yes.getValue());
        return materielDataService.list(queryWrapper);
    }

}
